﻿namespace Arms.Presentation.Web.Areas.Orders.Controllers
{
    using Arms.Application.Modules.Orders;
    using Arms.Presentation.Web.Areas.Orders.Models;
    using Arms.Presentation.Web.Controllers;
    using Arms.Presentation.Web.Extensions;
    using Kendo.Mvc.UI;
    using Kendo.Mvc.Extensions;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;
    using Arms.Application.Modules.Orders.DTOs;
    using Arms.Application.Modules.People.Customers;
    using Arms.Application.Modules.Products;

    public class OrderController : BaseController
    {
        private readonly IOrderService _orderService;
        private readonly IOrderQueryService _orderQueryService;
        private readonly ICustomerService _customerService;
        private readonly ICustomerQueryService _customerQueryService;
        private readonly IProductQueryService _productQueryService;

        public OrderController(IOrderService orderService,
                               IOrderQueryService orderQueryService,
                               ICustomerService customerService,
                               ICustomerQueryService customerQueryService,
                               IProductQueryService productQueryService)
        {
            _orderService = orderService;
            _orderQueryService = orderQueryService;
            _customerService = customerService;
            _customerQueryService = customerQueryService;
            _productQueryService = productQueryService;
        }

        public ActionResult GetOrderTypes()
        {
            return Json(_orderQueryService.GetOrderTypes(), JsonRequestBehavior.AllowGet);
        }

        [HttpGet]
        public ActionResult DiningRoom(int tableID, int orderHeaderID = 0)
        {
            OrderDiningRoomModel model = NewOrder<OrderDiningRoomModel>(orderHeaderID, 1);
            model.DiningRoomTableID = tableID;
            return View(model);
        }

        [HttpPost]
        public ActionResult DiningRoom(OrderDiningRoomModel model)
        {
            if (ModelState.IsValid)
            {
                int orderHeaderID = model.OrderHeaderID;

                if (orderHeaderID == 0)
                {
                    orderHeaderID = _orderService.CreateOrderHeader(model.OrderDate, null, model.DiningRoomTableID);
                }

                int orderID = _orderService.AddOrderToOrderHeader(model.OrderDate, orderHeaderID, null, null);

                if (orderID > 0)
                {
                    var productsInOrders = model.ProductPicker.Products.Select(x => new ProductsInOrderDTO()
                    {
                        ProductID = x.ID,
                        Quantity = x.Quantity
                    });

                    _orderService.AddProductsToOrder(orderID, productsInOrders.ToArray());
                    return RedirectToAction("Pending", "Order", "Orders");
                }
                else
                {
                    ModelState.AddModelError("", "Error creating order");
                }
            }

            return View(model);
        }

        [HttpGet]
        public ActionResult Delivery(int customerID = 0, int orderHeaderID = 0)
        {
            OrderDeliveryModel model = NewOrder<OrderDeliveryModel>(orderHeaderID, 0);
            model.DeliveryDate = DateTime.UtcNow;
            return View(model);
        }

        [HttpPost]
        public ActionResult Delivery(OrderDeliveryModel model)
        {
            if (ModelState.IsValid)
            {
                int orderHeaderID = model.OrderHeaderID;

                if (orderHeaderID == 0)
                {
                    orderHeaderID = _orderService.CreateOrderHeader(model.OrderDate, model.CustomerID, null);
                }

                int orderID = _orderService.AddOrderToOrderHeader(model.OrderDate, orderHeaderID, model.DeliveryDate, null);

                if (orderID > 0)
                {
                    var productsInOrders = model.ProductPicker.Products.Select(x => new ProductsInOrderDTO()
                    {
                        ProductID = x.ID,
                        Quantity = x.Quantity
                    });

                    _orderService.AddProductsToOrder(orderID, productsInOrders.ToArray());
                    return RedirectToAction("Pending", "Order", "Orders");
                }
                else
                {
                    ModelState.AddModelError("", "Error creating order");
                }
            }

            return View(model);
        }

        [HttpGet]
        public ActionResult Pickup(int customerID = 0, int orderHeaderID = 0)
        {
            OrderPickupModel model = NewOrder<OrderPickupModel>(orderHeaderID, 0);
            model.PickupDate = DateTime.UtcNow;
            return View(model);
        }

        [HttpPost]
        public ActionResult Pickup(OrderPickupModel model)
        {
            int orderHeaderID = model.OrderHeaderID;
            int customerID = model.CustomerID;

            if (customerID == 0 && !_customerQueryService.CustomerExists(model.CustomerName, model.CustomerPhone))
            {
                customerID = _customerService.AddCustomer(model.CustomerName, model.CustomerPhone);
            }
            else
            {
                customerID = _customerQueryService.FindCustomerID(model.CustomerName, model.CustomerPhone);
            }

            if (orderHeaderID == 0)
            {
                orderHeaderID = _orderService.CreateOrderHeader(model.OrderDate, customerID, null);
            }

            int orderID = _orderService.AddOrderToOrderHeader(model.OrderDate, orderHeaderID, null, model.PickupDate);

            if (orderID > 0)
            {
                var productsInOrders = model.ProductPicker.Products.Select(x => new ProductsInOrderDTO()
                {
                    ProductID = x.ID,
                    Quantity = x.Quantity
                });

                _orderService.AddProductsToOrder(orderID, productsInOrders.ToArray());
                return RedirectToAction("Pending", "Order", "Orders");
            }
            else
            {
                ModelState.AddModelError("", "Error creating order");
            }

            return View(model);
        }

        [HttpGet]
        public ActionResult View(int orderHeaderID)
        {
            OrderViewModel model = new OrderViewModel();
            model.OrderHeader = _orderQueryService.FindOrderHeader(orderHeaderID);
            model.Orders = _orderQueryService.GetOrders(orderHeaderID).ToList();
            model.Customer = _customerQueryService.FindCustomer(orderHeaderID);

            foreach (var order in model.Orders)
            {
                order.Products = _productQueryService.GetProductsInOrderWithQuantity(order.OrderID);
            }

            return View(model);
        }

        [HttpPost]
        public ActionResult Update(int orderHeaderID)
        {
            throw new NotImplementedException();
        }

        [HttpPost]
        public ActionResult Invoice(int orderHeaderID)
        {
            throw new NotImplementedException();
        }

        [HttpPost]
        public ActionResult Void(int orderHeaderID)
        {
            throw new NotImplementedException();
        }

        protected T NewOrder<T>(int orderHeaderID, int orderType) where T : OrderModel, new()
        {
            return new T() { OrderDate = DateTime.UtcNow, OrderHeaderID = orderHeaderID, OrderType = new Application.ListItemDTO() { ItemID = orderType } };
        }

        [HttpGet]
        public ActionResult Pending()
        {
            return View();
        }

        public ActionResult GetPendingOrders([DataSourceRequest] DataSourceRequest request)
        {
            ViewData["OrderHeaders"] = _orderQueryService.GetOrderHeaders();
            ViewData["Customers"] = _customerQueryService.GetCustomers();
            return Json(_orderQueryService.GetPendingOrders().ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
        }
    }
}
